import java.net.*;
import java.io.*;
import java.util.*;

/** ServerTalk4.java and LocalTalk2.java:
    One ServerTalk4.java and multiple LocalTalk2.java running instances
 can send and receive messages as objects to each other. The programs
 have the following features:

	1. The server accepts multiple client connections.
	2. One thread is started to handle all clinet connections.
	3. The exception cuased by broken connection is handled.
	4. Like ServerTalk2, ServerTalk3, the server will not be able
	   to handle clients of different speed. That is, the messages
	   received by the server will be alternatively from each of
	   of all clients. The un-intented result is caused by not being
	   able to test whether bytes on a object inputstream is avaiable
	   or not.

    Two problems to remember:
   	1. ObjectInputStream's available() doesnot return number > 0.
	2. The order to call getOutputStream() and getInputStream() 
	   makes difference.
*/
   
public class ServerTalk4 {
   public static void main(String args[] ) {
      ObjectInputStream in;
      ObjectOutputStream out;
      Vector vIn = new Vector();
      Vector vOut = new Vector();

      try {
        ServerSocket ssk = new ServerSocket(8900);
	Socket	     sk;
	Agent	     agent = new Agent(vIn, vOut ) ;
	agent.start();
        while ( true ) {
		sk = ssk.accept();
		// Strange: The order of following two statement is important.
		out = new ObjectOutputStream( sk.getOutputStream());
		in = new ObjectInputStream( sk.getInputStream());
		vIn.add(in); vOut.add(out);
		System.out.println("Size of vOut = " + vOut.size() +
				   "  Size of vIn = " + vIn.size()   );
        }
      } catch (Exception e) { e.printStackTrace(); }
   }
}

class Agent extends Thread {
   Socket sk;
   int    aNum; 
   Vector vIn, vOut;

   public Agent(Vector vIn, Vector vOut) { this.vIn = vIn; this.vOut = vOut; }

   public void run() {

      try {
	int mNum = 1;
	String message;

	ObjectInputStream in;
	ObjectOutputStream out;

	while ( true ) {
	  int i = 0 ;
	  try {
	    for ( i = 0; i < vOut.size(); i++ ) {
		message = "Server message " + (mNum ++);
		out = (ObjectOutputStream) vOut.get(i);
		out.writeObject( message );
		out.flush();
	    }
	    for ( i = 0; i < vIn.size(); i ++) {
		in = (ObjectInputStream) vIn.get(i);
		message = (String) in.readObject();
		System.out.println("Message received by Server: " + message);
	    }
	  } catch (IOException e) { vIn.remove(i); vOut.remove(i); }
	    sleep( (int)(Math.random() * 2000) + 500);
	}
      } catch (Exception e) { e.printStackTrace(); }
   }
}

